#include "ZPackage.h"
#include "ZGlobalFile\ZLibFun.h"
#include "ZGlobalFile\ZIdMgr.h"


///
ZPackageCtrlHead::ZPackageCtrlHead()
{
	ResetData();
}

ZPackageCtrlHead::~ZPackageCtrlHead()
{

}

int ZPackageCtrlHead::WriteToByteArr( QByteArray& byteArr ) const
{
	byteArr.append(&m_iHeadInfo, 1);
	byteArr.append((char*)(&m_iSubPackIndex), sizeof(int));
	byteArr.append((char*)(&m_iPackageId), sizeof(int));

	return byteArr.size();
}

int ZPackageCtrlHead::LoadFromByteArr( const QByteArray& byteArr )
{
	m_iHeadInfo = byteArr[0];
	QByteArray tmpByteArr;
	tmpByteArr = byteArr.mid(1, sizeof(int));
	m_iSubPackIndex = QByteArrayToInt(tmpByteArr);

	tmpByteArr = byteArr.mid(1+sizeof(int), sizeof(int));
	m_iPackageId = QByteArrayToInt(tmpByteArr);

	return 1+sizeof(int)+sizeof(int);
}

bool ZPackageCtrlHead::IsPackageCanSend() const
{
	return m_iPackageId > 0;
}

void ZPackageCtrlHead::ResetData()
{
	m_iPackageId = 0;
	m_iSubPackIndex = 0;
	m_iHeadInfo = 0;
}

void ZPackageCtrlHead::_setCtrlPack( bool bCtrlPack )
{
	if (bCtrlPack)
	{
		m_iHeadInfo = m_iHeadInfo | (~CTRL_PACK_OPT);
	}
	else
	{
		m_iHeadInfo = m_iHeadInfo & CTRL_PACK_OPT;
	}
}

bool ZPackageCtrlHead::_isCtrlPack() const
{
	return ((m_iHeadInfo | CTRL_PACK_OPT) != CTRL_PACK_OPT);
}

void ZPackageCtrlHead::_setEndPack( bool bEndPack )
{
	if (bEndPack)
	{
		m_iHeadInfo = m_iHeadInfo | (~END_PACK_OPT);
	}
	else
	{
		m_iHeadInfo = m_iHeadInfo & END_PACK_OPT;
	}
}

bool ZPackageCtrlHead::_isEndPack() const
{
	return ((m_iHeadInfo | END_PACK_OPT) != END_PACK_OPT);
}
///
void ZSubPackage::WriteToByteArr( QByteArray& byteArr ) const
{
	m_packHead.WriteToByteArr(byteArr);
	byteArr.append(m_subData);
}

void ZSubPackage::LoadFromByteArr( const QByteArray& byteArr )
{
	int iStartPos = m_packHead.LoadFromByteArr(byteArr);
	m_subData = byteArr.mid(iStartPos);
}

void ZSubPackage::ResetData()
{
	m_packHead.ResetData();
	m_subData.clear();
}

int ZSubPackage::GetPackID() const
{
	return m_packHead._getPackageId();
}

int ZSubPackage::GetPackIndex() const
{
	return m_packHead._getSubPackIndex();
}

bool ZSubPackage::IsEndPack() const
{
	return m_packHead._isEndPack();
}

bool ZSubPackage::IsCtrlPack() const
{
	return m_packHead._isCtrlPack();
}
//////////////////////////////////////////////////////////////////////////
ZPackage* ZPackageCreator::CreatePackBySubPack(const vecZSubPackage& vecSubPack)
{
	if (vecSubPack.size() < 1)
	{
		return NULL;
	}

	ZPackage* pNewPack = NULL;
	if(vecSubPack.front()->IsCtrlPack())
	{
		pNewPack = new ZCtrlPackage;
	}
	else
	{
		pNewPack = new ZPackage;
	}

	QByteArray wholeByteArr;
	for (auto it=vecSubPack.begin(); it!=vecSubPack.end(); it++)
	{
		if (!(*it)->m_subData.isEmpty())
		{
			wholeByteArr.append((*it)->m_subData);
		}
	}

	pNewPack->_loadFromByteArr(wholeByteArr);

	return pNewPack;
}
///
ZPackage::ZPackage(const QString& sUserDefType)
{
	m_sUserDefType = sUserDefType;
}

void ZPackage::SetPackHeadUseDefType( const QString& sUserDefType )
{
	m_sUserDefType = sUserDefType;
}

const QString& ZPackage::GetPackHeadUseDefType() const
{
	return m_sUserDefType;
}

void ZPackage::ClearData()
{
	m_data.clear();
}

void ZPackage::AppendData( const QByteArray& byteArr )
{
	m_data.append(byteArr);
}

void ZPackage::AppendData( const QString& sData )
{
	m_data.append(sData);
}

const QByteArray& ZPackage::GetData() const
{
	return m_data;
}

void ZPackage::SetData( const QByteArray& dataArr )
{
	m_data = dataArr;
}

quint32 ZPackage::SplitToSubPackage( vecZSubPackage& vecSubPack ) const
{
	QByteArray wholeByteArr;
	_writeToByteArr(wholeByteArr);
	vecQByteArray vecCutByteArr = g_SplitByteArray(wholeByteArr, UdpCutSize);

	if (vecCutByteArr.size() == 0)
	{
		return 0;
	}


	int iPackageId = g_CreateUniqueId();

	ZSubPackage* pSubPackage = NULL;
	vecQByteArray::size_type iSize = vecCutByteArr.size();
	for (vecQByteArray::size_type i=0; i<iSize; i++)
	{
		pSubPackage = new ZSubPackage;
		pSubPackage->m_packHead._setPackageId(iPackageId);
		if (i+1 == iSize)
		{
			pSubPackage->m_packHead._setEndPack(true);
		}
		pSubPackage->m_packHead._setSubPackIndex(i);
		pSubPackage->m_subData = vecCutByteArr[i];
		pSubPackage->m_packHead._setCtrlPack(false);
		vecSubPack.push_back(pSubPackage);
	}

	return vecSubPack.size();
}

void ZPackage::_writeToByteArr( QByteArray& byteArr ) const
{
	QDataStream out(&byteArr, QIODevice::WriteOnly);
	out << m_sUserDefType << m_data;
}

void ZPackage::_loadFromByteArr( QByteArray& byteArr )
{
	QDataStream in(&byteArr, QIODevice::ReadOnly);
	in >> m_sUserDefType >> m_data;
}
///
bool ZCtrlPackage::SetCtrlInfo(int iPackId, int iMaxSubPackIdRecved, const vecInt& vecSubPackLosted)
{
	m_iPackId = iPackId;
	m_vecSubPackLosted = vecSubPackLosted;
	m_iMaxSubPackIdRecved = iMaxSubPackIdRecved;
	return true;
}

quint32 ZCtrlPackage::SplitToSubPackage( vecZSubPackage& vecSubPack ) const
{
	ZPackage::SplitToSubPackage(vecSubPack);
	for (auto i=vecSubPack.begin(); i!=vecSubPack.end(); i++)
	{
		(*i)->m_packHead._setCtrlPack(true);
	}
	return vecSubPack.size();
}

void ZCtrlPackage::_writeToByteArr( QByteArray& byteArr ) const
{
	QDataStream out(&byteArr, QIODevice::WriteOnly);
	QString sType = ZReSendPackType;
	out << sType << m_iPackId << m_iMaxSubPackIdRecved << m_vecSubPackLosted;
}

void ZCtrlPackage::_loadFromByteArr( QByteArray& byteArr )
{
	m_iPackId = -1;
	m_vecSubPackLosted.clear();
	
	QDataStream in(&byteArr, QIODevice::ReadOnly);
	QString sType;
	in >> sType >> m_iPackId >> m_iMaxSubPackIdRecved >> m_vecSubPackLosted;
}
